feat(flashblocks rpc): Full revamp of X Layer custom flashblocks RPC layer#176
feat(flashblocks rpc): Full revamp of X Layer custom flashblocks RPC layer#176
Conversation
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…to state cache 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a tertiary tx hash index (HashMap<TxHash, Arc<CachedTxInfo>>) to ConfirmCache, enabling O(1) lookups for transaction_by_hash, transaction_by_hash_with_meta, and receipt_by_hash from confirmed flashblocks that are ahead of the canonical chain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add collect_cached_block_range_while helper that threads a predicate through both the provider prefix and cached suffix, enabling sealed_headers_while to serve confirmed flashblock headers instead of bypassing the cache entirely. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… rpc crate Consolidates flashblocks cache provider trait implementations (block, header, factory, receipt, transaction) into a single eth.rs override module in the rpc crate. Wires FlashblockStateCache into the node's RPC registration. Simplifies the cache layer to only manage state. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…an up cache interfaces 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidate the previously split flashblocks service setup and state cache creation into one cohesive `if let Some` block. This fixes a subtle bug where using `.map()` with `?` operators would produce `Option<Result<T, E>>` instead of the intended `Option<T>`, causing `?` to not propagate errors to the outer closure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… access Restructure ConfirmCache to store ExecutedBlock directly instead of just BlockAndReceipts, enabling state provider overlay for flashblock state queries. - Add ConfirmedBlock struct wrapping ExecutedBlock + receipts - Update insert/remove signatures to accept ExecutedBlock - Make PendingSequence.tx_index pub for state access - Fix execution cache test assertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cks state 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
f8a26bf to
5d96010
Compare
5d96010 to
6666f70
Compare
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the cumulative gas offset application from merge_suffix_results into the per-receipt execution loop so that receipts sent to the incremental root builder already carry the correct cumulative_gas_used. Refactor FlashblockReceipt::add_cumulative_gas_offset to operate on a single receipt instead of a slice. Also improve logging consistency and add target_index to execution trace. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…vider For incremental builds, resolve the state provider from the pending sequence block hash instead of the parent hash so the overlay trie anchors at the latest executed prefix. Thread the parent SealedHeader into PendingSequence so the EVM env and state root remain consistent across incremental steps. Pass evm_env directly to execute_block to avoid cloning the full ExecutionEnv. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ilds Incremental builds accumulate one revert entry per flashblock index via merge_transitions, but the engine persistence service expects a single revert per block. Flatten all revert transitions by keeping the earliest (parent-state) account info per address and merging storage slot reverts across transitions, preserving wipe_storage from later indices. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… engine Add a debug mode (--xlayer.flashblocks-debug-state-comparison) that compares ExecutedBlock bundle states, reverts, and trie data between the flashblocks RPC cache and the engine canonical state on each new canonical block. Also add a flag to disable pre-warming so the engine computes payloads independently for accurate comparison. The heavy comparison runs on a blocking thread to avoid stalling the canonical stream handler. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Expose a unified lookup across pending and confirm caches for ExecutedBlock by block number, simplifying the debug comparison to a single call instead of inline pending sequence matching. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop DeferredTrieData comparison (hashed_state + trie_updates) from the debug state comparison since trie data is computed independently by the engine and not meaningful for execution output equivalence checks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…_updates to engine Re-add hashed_state comparison to debug output since it validates the incremental BundleState produces the same hashed diff as fresh execution — critical for pre-warm correctness. Send empty trie_updates in the pre-warm payload instead of the incremental PreservedSparseTrie output, which produces incomplete trie_updates missing prefix leaf changes folded into pruned branches. The engine computes its own trie data fresh from hashed_state. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…matches 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review again for me |
|
Claude finished @sieniven's task in 6m 57s —— View job PR Review (Round 4): feat(flashblocks rpc): Full revamp of X Layer custom flashblocks RPC layerTasks:
Verification: All Previously Identified IssuesAll 17 issues across reviews 1–3 are correctly resolved. Spot-checked below.
New FindingsMinor:
|
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the promote-then-flush pattern that inserted the pending block into the confirm cache only to immediately evict it. The canonical chainstate already serves the block, so simply clearing the pending state is sufficient. Consolidate the duplicate pending clear paths into a single stale check and move the reorg/hash-mismatch early return first for clearer control flow. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Review (Round 4) — Resolution StatusThe fourth review found 2 minor issues. Resolution below:
The observation about duplicated flush-on-error logic in |
Move ExecutionTaskQueue type, trait, and constant from service.rs into cache/execution.rs so the task queue lives alongside the state cache it protects. The queue is now owned by FlashblockStateCache and flushed internally on reorg and read-path overlay errors, removing the need for callers to manage the flush externally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move ExecutionTaskQueue and related types from cache/execution.rs to cache/task.rs for clearer module naming. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
This PR revamps the entire flashblocks rpc layer design, similar to the previous Realtime-feature (RTA) cache capabilities on the since discontinued xlayer-erigon (refer to: https://github.com/okx/xlayer-erigon/tree/dev/zk/realtime).
Essentially, this revamp implements the full solution 2 mentioned in the upstream reth's issue discussion thread: paradigmxyz/reth#20491, which is a more elegant design to the complex op-reth's flashblock rpc layer that is tightly coupled to the underlying anchoring canonical chainstate.
In addition, the new design overhauls and optimizes the flashblocks sequence validation, which is encapsulates inside the new
FlashblockSequenceValidator. It aligns the sequence validation logic to the highly optimized upstream reth's engine payload validator ([ref].Motivations
The best design for allowing minimal latencies is to allow a full state accumulation from incoming flashblocks that are ahead of the canonical chainstate, while allowing for a hybrid sync approach that:
CHANGESET_CACHE_RETENTION_BLOCKS), once canonical chainstate catches uplatesttags) on flashblocks rpc tries to read from both the flashblocks state cache and underlying canon providerRevamped flashblocks RPC design
1. Flashblock cache layer
FlashblockStateCachelayer which includes both the pending state and confirm state caches2. Merklization
3. Execution optimizations for flashblocks sequence validation
4. Incremental execution support
5. In-memory overlay provider suppor
6. Flashblocks eth rpc extension
eth_sendRawTransactionSynceth_getRawTransactionByBlockHashAndIndexeth_getRawTransactionByBlockNumberAndIndex7. Remove sequence manager, revamp to RawCache
8. Add handlers for flashblocks state update logic
handle_flashblockshandler - handle receiving a raw flashblock, and updating the raw cachehandle_flashblocks_statehandler - handle spawning task execution for flashblocks sequence validation and updating the flashblocks state cachehandle_canonical_block- logic to handle canonical chainstate updates to flush flashblocks state cache layer, and also handle extreme cases like chain reorgs, etcSupported flashblocks eth APIs
Block apis
[✅]
eth_blockNumber[✅]
eth_getBlockByNumber[✅]
eth_getBlockByHash[✅]
eth_getBlockReceipts[✅]
eth_getBlockTransactionCountByNumber[✅]
eth_getBlockTransactionCountByHashTransaction apis
[✅]
eth_getTransactionByHash[✅]
eth_getRawTransactionByHash[✅]
eth_getTransactionReceipt[✅]
eth_getTransactionByBlockHashAndIndex[✅]
eth_getTransactionByBlockNumberAndIndex[✅]
eth_getRawTransactionByBlockHashAndIndex[✅]
eth_getRawTransactionByBlockNumberAndIndex[✅]
eth_sendRawTransactionSyncState apis
[✅]
eth_call[✅]
eth_estimateGas[✅]
eth_getBalance[✅]
eth_getTransactionCount[✅]
eth_getCode[✅]
eth_getStorageAtTODO:
Support eth_getLogs in the future
Design flaws on op-reth flashblocks rpc
On subsequent reth version upgrades (todo):
Todos: